#!/bin/python
# -*- coding: gb2312; mode:python ; tab-width:4 -*- ex:set tabstop=4 shiftwidth=4 expandtab: -*-

##########################################################
# PROJECT : WTS Server
# FILE    : messsage_analysis.py
# CREATION: 2007-08-20
# LICENSE : GPL
# $Id: message_analysis.py 15 2007-09-06 00:54:28Z hf $
##########################################################
"""
Packet Analysis

Usage : parser an octet stream to obtain a dict-like message
Author: Yuyan Sun
Revised: Wei Huangfu
Date  : 2007-08-20
"""

import re
import logging
import struct
import sys, traceback, os
import wtsglobal
import wtsstruct
import WtsXmlParser
from wtsmisc import calc, printExp, str2hex

class MessageAnalysis:
    """
    Class for parse octet packet to python dict
    """

    __slots__ = ["commonField","typedField"]
    NoneBuiltin = {'__builtins__': None,'True':True,'False':False, 'len':len}
    
    
    def __init__(self, xmlConfigFile=None):
        """
        initial from xml config
        @params xmlConfigFile: xml config file
        @return None
        """
        
        
        if xmlConfigFile==None: 
            xmlConfigFile = "packet_define_zn0x.xml"
           
        self.fc = WtsXmlParser.ParsePacketXML(xmlConfigFile)
        self.structParser = wtsstruct.Struct()

    def unpackField(self, msg, packet, rules):
        """
        internal function, used for unpack all fields from packet according to a rule
        @param msg: python dict
        @param packet: octet packet
        @param rules: dict, like self.commonField
        """
        """
        ========fc.commonFieldOnly==============
        [{'begin': 5, 'end': None, 'name': u'Length', 'format': '', 'title': u'Length', 'type': u'uint8'}, {'begin': 6, 'end': None, 'name': u'Cluster', 'format': '', 'title': u'Cluster', 'type': u'uint8'}, {'begin': 7, 'end': None, 'name': u'Type', 'format': '', 'title': u'Type', 'type': u'uint8'}, {'begin': 8, 'end': None, 'name': u'SubType', 'format': '', 'title': u'SubType', 'type': u'uint8'}, {'begin': 9, 'end': None, 'name': u'Data', 'format': u'hex', 'title': u'Data', 'type': u'binary'}]

        """
        print rules
        for i in rules:
            name = i["name"]
            fbegin = i["begin"]
            fend = i["end"]
            ftype = i["type"]
            try:
                s = self.structParser.unpack(ftype, packet[fbegin:fend] )
            except:
                logging.error("Unpack Error for Packet=[%s] with Format=%s @ field name=%s", str2hex(packet), rules, name)
##                raise
            msg[name] = s

    def analysis(self,packet):
        """
        analysis the input packte, differ the field depend on msg type
        @param packet: string; packet
        @return: message (dict), or {} if error
        """
        msg = {}
        try:
           
            self.unpackField(msg,packet,self.fc.commonFieldOnly)
            print msg
            for tname in self.fc.dataType:
                tcondition = self.fc.conditionByType[tname]
                tfield = self.fc.typedFieldOnly[tname]
                print tcondition
                print tname
                if calc(tcondition,msg,False):
                    self.unpackField(msg,packet,tfield)
                    msg['__DataType__']=tname
                    break
                else:
                    msg['__DataType__']="Undefined"
            return msg
        except:
##            printExp()
            logging.error("Drop Error formatted Packet")
            return {}
    
if __name__ == "__main__":
    print "Test msganalysis"
    pa='\x07\x07\x07\x07\x09\x00\x07\xc7\x00\x01\x00\x01\x02\x02'    
    segtool=MessageAnalysis()

    print segtool.analysis(pa)
    
    
    